package util;

import db.Player;
import mechanism.GoBangBoard;
import result.CodeMsg;
import result.Result;
import view.Board;
import view.Room;

import javax.swing.*;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.HashMap;
import java.util.Objects;

/**
 * @author 化尘成影
 * @Description
 * @date 2022/6/27 13:31
 */
public class Client {
    private static Socket socket = null;
    public static ObjectInputStream ois = null;
    public static ObjectOutputStream oos = null;
    public static JFrame jFrame;
    public static GoBangBoard goBangBoard;
    public static Board board;
    //volatile修饰符用来保证其它线程读取的总是该变量的最新的值
    public static volatile boolean exit = false;
    public static int count = 3;
    public static String username;
    public static boolean isContinue = true;

    public static void connection() throws Exception {
        socket = new Socket("127.0.0.1", 9919);
        ois = new ObjectInputStream(socket.getInputStream());
        oos = new ObjectOutputStream(socket.getOutputStream());
    }

    public static void clientResponse() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                Thread.currentThread().setName("chest");
                w:
                while (!exit) {
                    try {
                        String response = ois.readUTF();
                        switch (response) {
                            case "connect" -> {
                                System.out.println("收到connect");
                                String username = (String) ois.readObject();
                                JOptionPane.showMessageDialog(jFrame, username + "玩家进入了,游戏开始！");
                                Client.isContinue = true;
//                                rivalStillLive();
                                board.rival = username;
                                board.jLabel.setText("房间号：" + board.roomId + "  " + "本人:" + board.owner + "  " +
                                        "对手:" + board.rival);
                                goBangBoard.rival = new Player(username, "白棋玩家", false, false, "O", 3);
                                goBangBoard.isYour = goBangBoard.owner.getYour();
                            }
                            case "reply" -> {
                                HashMap<String, String> map = (HashMap<String, String>) ois.readObject();
                                board.chatShow.append("[" + map.get("fromUser") + "]：" + map.get("chatGoText") + "\n");
                            }
                            case "add" -> {
                                HashMap<String, String> map = (HashMap<String, String>) ois.readObject();
                                goBangBoard.addChess(Integer.parseInt(map.get("x")), Integer.parseInt(map.get("y")));
                            }
                            case "decide" -> {
                                String date = (String) ois.readObject();
                                int result = JOptionPane.showConfirmDialog(null, "对方想要" + date + ",是否同意？", "判断框",
                                        JOptionPane.YES_NO_OPTION);

                                if (result == 0) {
                                    switch (date) {
                                        case "重新开始" -> goBangBoard.restart();
                                        case "悔棋" -> goBangBoard.goBack();
                                    }
                                }

                                oos.writeUTF("result");
                                oos.flush();
                                oos.writeObject(result + "-" + date + "," + board.owner);
                                oos.flush();
                            }
                            case "answer" -> {
                                String date = (String) ois.readObject();
                                String[] split = date.split("-");

                                if (Integer.parseInt(split[0]) == 0) {
                                    JOptionPane.showMessageDialog(jFrame, "对方同意" + split[1]);
                                    switch (split[1]) {
                                        case "重新开始" -> goBangBoard.restart();
                                        case "悔棋" -> goBangBoard.goBack();
                                    }
                                } else {
                                    JOptionPane.showMessageDialog(jFrame, "对方不同意" + split[1]);
                                }
                                goBangBoard.isStart = true;
                                System.out.println(date);
                            }
                            case "win" -> {
                                String username = (String) ois.readObject();
                                System.out.println(username);
                                goBangBoard.surrender(username);
                            }
                            case "cBack" -> {
                                JOptionPane.showMessageDialog(jFrame, "对方退出，游戏结束");
                                Room room = new Room(goBangBoard.owner.getUsername());
                                room.setVisible(true);
                                jFrame.dispose();
                            }
                            case "comeback" -> {
                                break w;
                            }
                            case "heartBeatFromServer" -> {
                                oos.writeUTF("heartBeatFromClient");
                                oos.flush();
                            }
                            case "isStillLive" -> {
//                                System.out.println("受到");
                            }
                            case "isLive" -> {
                                String result = (String) ois.readObject();
//                                if(result.equals("No")){
//                                    JOptionPane.showMessageDialog(jFrame, "对方掉线，回到房间");
//                                    Room room = new Room(goBangBoard.owner.getUsername());
//                                    room.setVisible(true);
//                                    jFrame.dispose();
//                                }
                            }
                            case "breakDown" -> {
                                JOptionPane.showMessageDialog(jFrame, "对方掉线，回到房间");
                                Room room = new Room(goBangBoard.owner.getUsername());
                                room.setVisible(true);
                                jFrame.dispose();
                                isContinue = false;
                                break w;
                            }
                            default -> {
                                System.out.println("无法响应");
                            }
                        }
                    } catch (Exception e) {
                        JOptionPane.showMessageDialog(jFrame, "服务器错误");
                    }
                }
            }
        }).start();
    }

    public static Result request(String type, HashMap<String, String> date, Boolean haveReturn) {
        try {
            Result result = new Result();
            try {
                oos.writeUTF(type);
                oos.flush();
                oos.writeObject(date);
                oos.flush();
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
            if (haveReturn) {
                try {
                    result = (Result) ois.readObject();
                } catch (IOException | ClassNotFoundException ioException) {
                    ioException.printStackTrace();
                }
                return result;
            } else {
                return null;
            }
        } catch (Exception e) {
            String message = e.getMessage();
            if (Objects.equals(message, "Connection reset by peer") || Objects.equals(message, "Connection reset")) {
                return new Result(new CodeMsg(404, "与服务器断开连接"), null);
            }
            e.printStackTrace();
        }
        return new Result(new CodeMsg(404, "与服务器断开连接"), null);
    }

    public static void rivalStillLive(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (isContinue){
                    try {
                        oos.writeUTF("rivalIsLive");
                        oos.writeObject(board.owner);
                        oos.flush();
                        Thread.sleep(5000);
                    } catch (Exception e) {
                        e.printStackTrace();
                        System.out.println("没了");
                        break;
                    }
                }
            }
        }).start();
    }

    public static void serverStillLive() {
        //心跳包
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        oos.writeUTF("live");
                        oos.flush();

                        try {
                            Thread.sleep(3000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    } catch (Exception e) {
                        System.out.println("服务器断线");
                        //尝试重连，共三次
                        try {
                            connection();
                            count = 3;
                            System.out.println("重连成功");
                        } catch (Exception ee) {
                            count--;
                            System.out.println("重连失败，剩余" + count + "次");
                            if (count == 0) {
                                System.out.println("重连失败，强制断线");
                                System.exit(0);
                            }
                            try {
                                Thread.sleep(5000);
                            } catch (InterruptedException ex) {
                                ex.printStackTrace();
                            }
                        }
                    }
                }
            }
        }).start();
    }

    public static void closeAll() {
        try {
            ois.close();
            oos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}